<template>
  <div class="center systemPage-wrapper">
    <flowAttribute v-if="flowVisible" :activeModel="flowModel" @close="hideFlow" @ok="saveFlowAttribute"></flowAttribute>
    <!--  -->
    <nodeAttribute v-if="nodeVisible" :activeNode="actNode" :isNodeType="nodeType" @close="hide" @ok="saveNode">
    </nodeAttribute>
    <linkAttribute v-if="linkVisible" :activeLink="actLink" @close="hideLink" @ok="saveLink"></linkAttribute>
    <winAdd v-if="showWind" @close="closeWind" @ok="workflowclasssave" :title="addtitle" :activeItem="flowClass"></winAdd>
    <winFlowView v-if="showFlowView" :wfInstId="wfInstId" :instNodeId="instNodeId" @close="close"></winFlowView>
    <flowSend v-if="showFlowSend" @close="closeFlowSend" @ok="FlowSendsave" :wfClassId="wfClassId"
      :instNodeId="instNodeId" :sendtype="sendtype" :var="null" :deptId="1" :dataTable="'w_user'" :jhId="1" :dataId="1">
    </flowSend>
    <div class="topbar">
      <span class="iconfont iconxitongpingtai-liuchengguanli"></span>
      <span>流程管理</span>
    </div>
    <div class="content-background content">
      <pageMenu :menuitems="menuitems" :selectShow="false" @itemclick="itemclick" @itemIconClick="itemIconClick"
        @add="add" :activeitem="activeitem" @search="search" :dropmenus="dropmenus" @dropitemclick="dropitemclick">
      </pageMenu>
      <div class="page-flow-detail" v-if="showView">
        <div id="sample" style="height: 100%">
          <div class="tool">
            <flowHeader style="width: calc(100% - 200px)" @openFlowAttribute="openFlowAttribute" @save="saveData"
              @writeJson="writeJson" @delflow="delflow" @clone="clone" @startflow="startflow" @sendflow="sendflow">
            </flowHeader>
            <div class="version" style="width: 200px; text-align: right; margin-right: 15px">
              <span>版本选择:</span>
              <el-select class="systemInput" v-model="version" style="width: 100px; height: 24px"
                @change="checkDataChange">
                <el-option v-for="item in versions" :key="item.id" :label="item.version" :value="item.id"
                  style="width: 100px"></el-option>
              </el-select>
            </div>
          </div>
          <div style="
              width: 100%;
              height: calc(100% - 32px);
              display: flex;
              justify-content: space-between;
              border-bottom-right-radius: 4px;
            ">
            <div id="myPaletteDiv"></div>
            <div id="myDiagramDiv"></div>
            <br />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import go from "gojs";
import qs from "qs";
import nodeAttribute from "../components/flow/nodeAttribute.vue";
import linkAttribute from "../components/flow/linkAttribute.vue";
import flowAttribute from "../components/flow/flowAttribute.vue";
import pageMenu from "../components/pageMenu.vue";
import winAdd from "../components/winAdd.vue";
import flowHeader from "../components/flow/flowHeader.vue";
import winFlowView from "@/system/components/winFlowView.vue";
import {
  workflowclassquery,
  workflowdetail,
  workflowclasssave,
  workflowclassdelete,
  workflowsave,
  workflowversion,
  workflowdelete,
} from "@/system/api/flowManage";
import flowSend from "@/system/components/flowSend.vue";
import { deepCopy } from "@/utils/public";

let gmake = go.GraphObject.make;

export default {
  name: "gojs",
  components: {
    pageMenu,
    flowHeader,
    nodeAttribute,
    flowAttribute,
    linkAttribute,
    winAdd,
    winFlowView,
    flowSend,
  },
  props: {},
  data() {
    return {
      flowVisible: false,
      nodeVisible: false,
      linkVisible: false,
      showView: true,
      activeitem: -1,
      menuitems: [],
      versions: [],
      dropmenus: [
        {
          name: "编辑",
          iconPosition: "before",
          iconname: "editicon",
          value: 1,
        },
        {
          name: "删除",
          iconPosition: "before",
          iconname: "delicon",
          value: 2,
        },
      ],
      myPalette: null,
      myDiagram: null,
      lightText: "whitesmoke",
      tedge: {
        code: null,
        fnodeCode: null,
        tnodeCode: null,
      },
      tnode: {
        code: null,
        runType: 2,
        grade: 0,
      },
      usedkeys: [],
      version: null,
      flowModel: {
        classId: null,
        code: null,
        version: 1.0,
        active: true,
        jpush: true,
        sms: false,
        node: [],
        edge: [],
        // userVars: [],
        vvar: [],
      },
      model: {
        class: "GraphLinksModel",
        linkFromPortIdProperty: "fromPort",
        linkToPortIdProperty: "toPort",
        nodeDataArray: [],
        linkDataArray: [],
      },
      activemodel: null,
      showFlowView: false,
      actGnode: null,
      actGlink: null,
      actNode: null,
      actLink: null,
      workflowparam: {
        content: "",
        pageIndex: 0,
        pageSize: 0,
      },
      flowClass: null,
      showWind: false,
      addtitle: "",
      flowClassId: null,
      showFlowSend: false,
      //测试变量 要删除
      instNodeId: null,
      sendtype: null,
      wfClassId: null,
      isDiagramChange: false,//流程图是否更改
      nodeType: 'node',//nodeAttribute中控制显示
      textFontSize: "22",//文本字体大小
      isIconClick: false,//当前用户是否编辑流程名称
    };
  },
  mounted() {
    //查询流程类信息
    this.workflowclassquery();

    let self = this;
    this.myDiagram = gmake(
      go.Diagram,
      "myDiagramDiv", // 网格锁定must name or refer to the DIV HTML element
      {
        scale: 1.0, //初始视图大小比例
        initialContentAlignment: go.Spot.Center,
        allowDrop: true, // must be true to accept drops from the Palette
        scrollsPageOnFocus: false,
        "undoManager.isEnabled": true, // enable undo & redo
        "grid.visible": true, //显示网格
        padding: 10,
        allowCopy: true,
        allowZoom: true,
        allowRelink: true,
        isReadOnly: true,
        //TODO  新增  
        allowHorizontalScroll: false,//水平滚动条  
        autoScale: go.Diagram.Uniform,//画布比例自适应
        grid: gmake(
          go.Panel,
          "Grid",
          gmake(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5 }),
          gmake(go.Shape, "LineH", {
            stroke: "gray",
            strokeWidth: 0.5,
            interval: 10,
          }),
          gmake(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5 }),
          gmake(go.Shape, "LineV", {
            stroke: "gray",
            strokeWidth: 0.5,
            interval: 10,
          })
        ),
        BackgroundDoubleClicked: function (e) {
          if (!e.diagram.isReadOnly) {
            self.flowVisible = true;
          }
        },
        // '*******添加配置--开始*******'
        nodeSelectionAdornmentTemplate: gmake(
          go.Adornment,
          "Auto",
          gmake(go.Shape, "Rectangle", {
            fill: "white",
            stroke: null,
          })
        ),
        // '*******添加配置--结束*******'
        //          allowRelink:false,
        "draggingTool.isGridSnapEnabled": true, //自动锁定
      }
    );

    let graygrad = gmake(go.Brush, "Linear", {
      0: "#F5F5F5",
      1: "#00A9C9",
    }); // 定义图表格式刷

    this.myDiagram.nodeTemplateMap.add(
      "all",
      gmake(
        go.Node,
        "Spot",
        self.nodeStyle(),
        {
          resizable: true,
          resizeObjectName: "PANEL",
          doubleClick: function (e, node) {
            if (node.data.key.toString().indexOf("N-") > -1) {
              self.actNode = self.getModelNode(node.data.key);
              self.actGnode = node;
              self.nodeType = 'node';
              self.nodeVisible = true;
            }
          },
          //	            isShadowed: true,//加阴影
        },
        gmake(
          go.Panel,
          "Auto",
          gmake(go.Shape, "RoundedRectangle", {
            fill: "#0099cc",
            stroke: "black",
            strokeWidth: 0,
            //								parameter1: 15,//可以设置弧度
            name: "nodeshape",
            // minSize: new go.Size(60, 30), //设置了大小，那么手动调节的地方也要设置
          }),
          gmake(
            go.TextBlock,
            {
              font: "bold 12px Helvetica, Arial, sans-serif",
              stroke: "#fff", //stroke  字体
              wrap: go.TextBlock.WrapFit,
              textAlign: "center",
              editable: false,//节点是否可编辑，默认为true
              name: "nodetext",
              //TODO 结束节点图形大小设置
              margin: 10,
            },
            new go.Binding("text").makeTwoWay(),

            new go.Binding("nodestate").makeTwoWay()
          )
        ),
        new go.Binding("width").makeTwoWay(),
        new go.Binding("height").makeTwoWay(),
        // three named ports, one on each side except the top, all output only:
        this.makePort("T", go.Spot.Top, true, true),
        this.makePort("L", go.Spot.Left, true, true),
        this.makePort("R", go.Spot.Right, true, true),
        this.makePort("B", go.Spot.Bottom, true, true)
      )
    );
    graygrad = gmake(go.Brush, "Linear", {
      0: "#F5F5F5",
      1: "#79C900",
    }); // 定义图表格式刷

    this.myDiagram.nodeTemplateMap.add(
      "Start",
      gmake(
        go.Node,
        "Spot",
        self.nodeStyle(),
        {
          resizable: true,
          resizeObjectName: "PANEL",
          doubleClick: function (e, node) {
            if (node.data.key.toString().indexOf("N-") > -1) {
              self.actNode = self.getModelNode(node.data.key);
              self.actGnode = node;
              self.nodeType = 'node';
              self.nodeVisible = true;
            }
          },
          //	            isShadowed: true,//加阴影
        },
        gmake(
          go.Panel,
          "Auto",
          gmake(
            go.Shape,
            "Ellipse",
            {
              fill: "#00AD5F",
              stroke: "black",
              // width:10,
              // height:0,
              strokeWidth: 0,
              name: "nodeshape",
              // minSize: new go.Size(20,20), //设置了大小，那么手动调节的地方也要设置
            },
            new go.Binding("figure", "figure")
          ),
          gmake(
            go.TextBlock,
            "Start",
            {
              font: "bold 12px Helvetica, Arial, sans-serif",
              stroke: "#fff",
              textAlign: "center",
              name: "nodetext",
              editable: false,
              //TODO 开始节点图形大小设置
              margin: 8,
            },
            new go.Binding("text").makeTwoWay(),
            new go.Binding("nodestate").makeTwoWay()
          )
        ),
        new go.Binding("width").makeTwoWay(),
        new go.Binding("height").makeTwoWay(),
        this.makePort("T", go.Spot.Top, true, false),
        this.makePort("L", go.Spot.Left, true, false),
        this.makePort("R", go.Spot.Right, true, false),
        this.makePort("B", go.Spot.Bottom, true, false)
      )
    );
    graygrad = gmake(go.Brush, "Linear", {
      0: "#F5F5F5",
      1: "#DC3C00",
    }); // 定义图表格式刷
    self.myDiagram.nodeTemplateMap.add(
      "End",
      gmake(
        go.Node,
        "Spot",
        this.nodeStyle(),
        {
          resizable: true,
          resizeObjectName: "PANEL",
          //	            isShadowed: true,//加阴影
          doubleClick: function (e, node) {
            if (node.data.key.toString().indexOf("N-") > -1) {
              self.actNode = self.getModelNode(node.data.key);
              self.actGnode = node;
              self.nodeType = 'node';
              self.nodeVisible = true;
            }
          },
        },
        gmake(
          go.Panel,
          "Auto",
          gmake(go.Shape, "Ellipse", {
            //	              minSize: new go.Size(35, 35),
            fill: "#CE0620",
            stroke: "black",
            strokeWidth: 0,
            name: "nodeshape",
            // minSize: new go.Size(60, 60), //设置了大小，那么手动调节的地方也要设置
          }),
          gmake(
            go.TextBlock,
            "End",
            {
              font: "bold 12px Helvetica, Arial, sans-serif",
              stroke: "#fff",
              textAlign: "center",
              name: "nodetext",
              editable: false,
              //TODO 结束节点图形大小设置
              margin: 8,
            },
            new go.Binding("text").makeTwoWay(),
            new go.Binding("nodestate").makeTwoWay()
          )
        ),
        new go.Binding("width").makeTwoWay(),
        new go.Binding("height").makeTwoWay(),
        this.makePort("T", go.Spot.Top, false, true),
        this.makePort("L", go.Spot.Left, false, true),
        this.makePort("R", go.Spot.Right, false, true),
        this.makePort("B", go.Spot.Bottom, false, true)
      )
    );
    //	      self.myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
    //	      self.myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Link.Orthogonal; //线的转弯
    self.myDiagram.nodeTemplateMap.add(
      "textblo",
      gmake(
        go.Node,
        "Auto",
        self.nodeStyle(),
        {
          resizable: true,
          resizeObjectName: "PANEL",
          text: "node",
          doubleClick: function (e, node) {
            console.log(e)
            console.log(node)
            self.actNode = self.getModelNode(node.data.key);
            self.actGnode = node;
            self.nodeType = 'text';
            // self.$set(self.actNode,"fontSize",node.data.fontSize.split("pt")[0]);
            self.$set(self.actNode, "fontType", node.data.fontSize.split("pt")[0]);
            // self.$set(self.actNode,"fontType",self.textFontSize);
            self.$set(self.actNode, "fontColor", node.data.color);
            self.$set(self.actNode, "backGroundColor", node.data.backgroundColor);
            self.nodeVisible = true;
          },
          // isShadowed: true,//加阴影
        },
        gmake(
          go.Panel,
          "Auto",
          gmake(
            go.Shape,
            {
              fill: "transparent",
              stroke: "#607d8b",
              strokeWidth: 0,
              name: "nodeshape",
              minSize: new go.Size(60, 30), //设置了大小，那么手动调节的地方也要设置
            },
            new go.Binding("text").makeTwoWay(),
          ),
          gmake(
            go.TextBlock,
            {
              margin: 5,
              wrap: 30,
              textAlign: "center",
              //  font: "22px Arial",
              // stroke:self.nodeTextColor, //"black"
              name: "nodetext",
              editable: false,
            },
            new go.Binding("text").makeTwoWay(),
            new go.Binding("nodestate").makeTwoWay(),
            //新增,动态修改文本颜色 大小及背景色
            new go.Binding("stroke", "color").makeTwoWay(),
            new go.Binding("font", "fontSize").makeTwoWay(),
            new go.Binding("background", "backgroundColor").makeTwoWay(),
          ),
          new go.Binding("text").makeTwoWay(),
        )
      )
    );
    graygrad = gmake(go.Brush, "Linear", {
      0: "#F5F5F5",
      1: "#666",
    }); // 定义图表格式刷
    self.myDiagram.nodeTemplateMap.add(
      "Comment",
      gmake(
        go.Node,
        "Spot",
        self.nodeStyle(),
        {
          resizable: true,
          resizeObjectName: "PANEL",
          doubleClick: function (e, node) {
            if (node.data.key.toString().indexOf("N-") > -1) {
              self.actNode = self.getModelNode(node.data.key);
              self.actGnode = node;
              self.nodeType = 'node';
              self.nodeVisible = true;
            }
          },
          // isShadowed: true,//加阴影
        },
        gmake(
          go.Panel,
          "Auto",
          gmake(go.Shape, "Diamond", {
            //	              minSize: new go.Size(60, 30),
            fill: "#6cf",
            stroke: "black",
            strokeWidth: 0,
            name: "nodeshape",
            // minSize: new go.Size(30, 30), //设置了大小，那么手动调节的地方也要设置
          }),
          gmake(
            go.TextBlock,
            "???",
            {
              wrap: go.TextBlock.WrapFit,
              textAlign: "center",
              font: "bold 12px Helvetica, Arial, sans-serif",
              stroke: "#fff",
              name: "nodetext",
              editable: false,
            },
            new go.Binding("text").makeTwoWay(),
            new go.Binding("nodestate").makeTwoWay()
          )
        ),
        new go.Binding("width", function () {
          return 60;
        }).makeTwoWay(),
        new go.Binding("height", function () {
          return 60;
        }).makeTwoWay(),
        this.makePort("T", go.Spot.Top, true, true),
        this.makePort("L", go.Spot.Left, true, true),
        this.makePort("R", go.Spot.Right, true, true),
        this.makePort("B", go.Spot.Bottom, true, true)
      )
    );
    self.myDiagram.linkTemplate = gmake(
      go.Link, // the whole link panel
      {
        routing: go.Link.AvoidsNodes,
        curve: go.Link.JumpOver,
        corner: 5,
        toShortLength: 4,
        relinkableFrom: true,
        relinkableTo: true,
        reshapable: true,
        resegmentable: true,
        selectionAdorned: false,
        mouseEnter: function (e, link) {
          link.findObject("HIGHLIGHT").stroke = "rgba(30,144,255,0.2)";
        },
        mouseLeave: function (e, link) {
          link.findObject("HIGHLIGHT").stroke = "transparent";
        },
        doubleClick: function (e, link) {
          self.actLink = self.getModelLink(link.data.key);
          self.actGlink = link;
          self.linkVisible = true;
        },
      },
      new go.Binding("points").makeTwoWay(),
      gmake(
        go.Shape, // the highlight shape, normally transparent
        {
          isPanelMain: true,
          strokeWidth: 8,
          stroke: "transparent",
          name: "HIGHLIGHT",
        }
      ),
      gmake(
        go.Shape, // the link path shape
        {
          isPanelMain: true,
          stroke: "gray",
          strokeWidth: 2,
        },
        new go.Binding("stroke", "isSelected", function (sel) {
          return sel ? "dodgerblue" : "gray";
        }).ofObject()
      ),
      gmake(
        go.Shape, // the arrowhead
        {
          toArrow: "standard",
          stroke: "gray",
          fill: "gray",
        }
      ),
      gmake(
        go.Panel,
        "Auto", // the link label, normally not visible
        {
          visible: true,
          cursor: "move",
        },
        new go.Binding("visible", "visible").makeTwoWay(),
        gmake(
          go.Shape,
          "RoundedRectangle", // the label shape
          {
            fill: "transparent",
            stroke: null,
          }
        ),
        gmake(
          go.TextBlock,
          " ", // the label
          {
            textAlign: "center",
            font: "10pt helvetica, arial, sans-serif",
            stroke: "#999",
            editable: false,
          },
          new go.Binding("text").makeTwoWay(),
          new go.Binding("name").makeTwoWay()
        )
      )
    ); //线上文字

    this.myPalette = gmake(
      go.Palette,
      "myPaletteDiv", // must name or refer to the DIV HTML element
      {
        scrollsPageOnFocus: false,
        allowZoom: false,
        allowVerticalScroll: false,
        padding: 20,
        nodeSelectionAdornmentTemplate: gmake(
          go.Adornment,
          "Auto",
          gmake(go.Shape, "Rectangle", {
            fill: "white",
            stroke: null,
          })
        ),
        //makeTwoWay()进行双向绑定
        // share the templates used by myDiagram
        nodeTemplateMap: self.myDiagram.nodeTemplateMap, // 节点（node）/线（link）的动态添加及样式

        model: new go.GraphLinksModel([
          // specify the contents of the Palette
          {
            text: "开始",
            category: "Start",
            width: "60",
            height: "60",
            nodestate: 0,
          },
          {
            text: "节点",
            category: "all",
            width: "90",
            height: "40",
            nodestate: 2,
          },
          {
            text: "判断",
            category: "Comment",
            width: "90",
            height: "50",
            nodestate: 3,
          },
          {
            text: "结束",
            category: "End",
            width: "60",
            height: "60",
            nodestate: 1,
          },
          {
            text: "文本",
            category: "textblo",
            width: "100",
            height: "40",
            nodestate: 2,
            color: '#000000',
            fontSize: self.textFontSize + 'pt helvetica, arial, sans-serif',
            backgroundColor: null
          },
        ]),
      }
    );
    this.myDiagram.model = go.Model.fromJson(this.model);
    this.myDiagram.commandHandler.doKeyDown = function () {
      let e = self.myDiagram.lastInput;
      if (!e.diagram.isReadOnly) {
        //只读的时候，就不能编辑
        let control = e.control || e.meta;
        let shift = e.shift || e.meta;
        let addH = 0;
        let addw = 0;
        if (e.key == "Up") {
          addH = -0.5;
        }
        if (e.key == "Down") {
          addH = 0.5;
        }
        if (e.key == "Left") {
          addw = -0.5;
        }
        if (e.key == "Right") {
          addw = 0.5;
        }
        if (control) {
          if (
            e.key == "Up" ||
            e.key == "Down" ||
            e.key == "Left" ||
            e.key == "Right"
          ) {
            for (let it = self.myDiagram.selection.iterator; it.next();) {
              let part = it.value;
              let x = part.location.x + addw;
              let y = part.location.y + addH;
              self.myDiagram.model.setDataProperty(
                part,
                "location",
                new go.Point(x, y)
              );
            }
            return;
          }
        }
        if (shift) {
          if (
            e.key == "Up" ||
            e.key == "Down" ||
            e.key == "Left" ||
            e.key == "Right"
          ) {
            for (let it = self.myDiagram.selection.iterator; it.next();) {
              let part = it.value;
              let x = part.qc.width + addw;
              let y = part.qc.height + addH;
              self.myDiagram.model.setDataProperty(
                part,
                "desiredSize",
                new go.Size(x, y)
              );
            }
            return;
          }
        }
        //			    let key = e.key;
        go.CommandHandler.prototype.doKeyDown.call(this);
      }
    };
    //监听节点和连线的文字更改
    this.myDiagram.addDiagramListener("TextEdited", function (e) {
      console.log('TextEdited')
      self.isDiagramChange = true;
    })
    //TODO 监听节点的新增、删除、移动等操作
    this.myDiagram.addDiagramListener("ChangedSelection", function (e) {
      console.log('ChangedSelection')
      self.isDiagramChange = true;
    })

    this.myDiagram.addDiagramListener("ExternalObjectsDropped", function (e) {
      console.log('得到从palette拖过来的节点')
      e.subject.each(function (part) {
        //TODO 得到从palette拖过来的节点
        let tkey = self.getKey();
        let tnode = deepCopy(self.tnode);
        self.$set(tnode, "code", tkey);
        self.$set(tnode, "name", part.data.text);
        self.$set(tnode, "runType", part.data.nodestate);
        self.flowModel.node.push(tnode);
        self.myDiagram.model.setKeyForNodeData(part.data, tkey);
        //						self.myDiagram.model.setDataProperty(part.data, 'code', tkey);
        part.height = Number(part.data.height);
        part.width = Number(part.data.width);
      });
    });
    this.myDiagram.addDiagramListener("LinkDrawn", function (e) {
      //TODO 监听线生成事件
      console.log('监听线生成事件')
      let tkey = self.getKey(0);
      let tlink = deepCopy(self.tlink);
      self.$set(tlink, "code", tkey);
      let ttext = "发送";
      self.$set(tlink, "name", ttext);
      self.$set(tlink, "fnodeCode", e.subject.fromNode.key); //fromNode
      self.$set(tlink, "tnodeCode", e.subject.toNode.key);
      self.flowModel.edge.push(tlink);
      self.myDiagram.model.setKeyForNodeData(e.subject.data, tkey);
      //				self.myDiagram.model.setDataProperty(e.subject.data, 'code', tkey);
      self.myDiagram.model.setDataProperty(e.subject.data, "text", ttext);
    });

    this.myDiagram.addDiagramListener("SelectionDeleted", function (e) {
      //监听删除事件
      console.log('监听删除事件')
      e.subject.each(function (part) {
        self.delnodeORlink(part.data);
      });
    });
    this.myDiagram.addModelChangedListener(function (evt) {
      // ignore unimportant Transaction events
      if (!evt.isTransactionFinished) return;
      var txn = evt.object; // a Transaction
      if (txn === null) return;
      // iterate over all of the actual ChangedEvents of the Transaction
      txn.changes.each(function (e) {
        // record node insertions and removals
        if (e.change === go.ChangedEvent.Property) {
          if (e.modelChange === "linkFromKey") {
            let newFromId = "";
            self.flowModel.node.forEach((node, index) => {
              if (node.code == e.newValue) {
                newFromId = node.id;
              }
            });
            let tindex = -1;
            self.to = e.object.to;
            self.from = e.oldValue;
            self.flowModel.edge.forEach((edge, index) => {
              if (edge.fnodeCode == self.from && edge.tnodeCode == self.to) {
                tindex = index;
                self.flowModel.edge[tindex].fnodeCode = e.newValue;
                self.flowModel.edge[tindex].fnodeId = newFromId;
              }
            });
          } else if (e.modelChange === "linkToKey") {
            let newToId = "";
            self.flowModel.node.forEach((node, index) => {
              if (node.code == e.oldValue) {
                newToId = node.id;
              }
            });
            let tindex = -1;
            self.from = e.object.from;
            self.to = e.oldValue;
            self.flowModel.edge.forEach((edge, index) => {
              if (edge.fnodeCode == self.from && edge.tnodeCode == self.to) {
                tindex = index;
                self.flowModel.edge[tindex].tnodeCode = e.newValue;
                self.flowModel.edge[tindex].fnodeId = newToId;
              }
            });
          }
        }
        // else if (
        //   e.change === go.ChangedEvent.Insert &&
        //   e.modelChange === "linkDataArray"
        // ) {
        // } else if (
        //   e.change === go.ChangedEvent.Remove &&
        //   e.modelChange === "linkDataArray"
        // ) {
        // }
      });
    });
  },
  methods: {
    delnodeORlink(data) {
      if (data.key.toString().indexOf("N-") > -1) {
        let tindex = -1;
        this.flowModel.node.forEach((node, index) => {
          if (node.code == data.key) {
            tindex = index;
          }
        });
        if (tindex > -1) {
          this.flowModel.node.splice(tindex, 1);
        }
      }

      if (data.key.toString().indexOf("L-") > -1) {
        let tindex = -1;
        this.flowModel.edge.forEach((edge, index) => {
          if (edge.code == data.key) {
            tindex = index;
          }
        });
        if (tindex > -1) {
          this.flowModel.edge.splice(tindex, 1);
        }
      }
    },
    getKey(type = 1) {
      let tkey = this.randomString(14);
      while (this.usedkeys.indexOf(tkey) > -1) {
        tkey = this.randomString(14);
      }
      if (type == 1) {
        tkey = "N-" + tkey;
      } else {
        tkey = "L-" + tkey;
      }
      return tkey;
    },
    randomString(len) {
      len = len || 32;
      var gmakechars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; ///****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/  ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678

      var maxPos = gmakechars.length;
      var pwd = "";
      for (let i = 0; i < len; i++) {
        pwd += gmakechars.charAt(Math.floor(Math.random() * maxPos));
      }
      return pwd;
    },
    checkDataChange(e) {
      this.workflowdetailByid();
    },
    zoom() {
      this.myDiagram.commandHandler.increaseZoom();
    },
    reducible() {
      this.myDiagram.commandHandler.decreaseZoom();
    },
    nodeStyle(e, obj) {
      let _this = this;
      return [
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
          go.Point.stringify
        ),
        {
          locationSpot: go.Spot.Center,
          mouseEnter: function (e, obj) {
            _this.showPorts(obj.part, true);
          },
          mouseLeave: function (e, obj) {
            _this.showPorts(obj.part, false);
          },
        },
      ];
    },
    showPorts(node, show) {
      var diagram = node.diagram;
      if (!diagram || diagram.isReadOnly || !diagram.allowLink) return;
      node.ports.each(function (port) {
        port.stroke = show ? "white" : null;
      });
    },
    //当鼠标选中的时候出现可以连线的点，一般有上下左右四个点
    makePort(name, spot, output, input) {
      //不能用demo4的  makePort  要不然边框会缺失
      // the port is basically just a small circle that has a white stroke when it is made visible
      return go.GraphObject.make(go.Shape, "Circle", {
        fill: "transparent",
        stroke: null, // this is changed to "white" in the showPorts function
        desiredSize: new go.Size(8, 8),
        alignment: spot,
        alignmentFocus: spot, // align the port on the main Shape
        portId: name, // declare this object to be a "port"
        fromSpot: spot,
        toSpot: spot, // declare where links may connect at this port
        fromLinkable: output,
        toLinkable: input, // declare whether the user may draw links to/from here
        cursor: "pointer", // show a different cursor to indicate potential link point
      });
    },
    hide() {
      this.nodeVisible = false;
      this.actGnode = null;
      this.actNode = null;
      this.nodeType = "node";
    },
    saveNode(v) {
      //保存节点属性 并关弹出的节点属性界面
      this.myDiagram.model.setDataProperty(this.actGnode.data, "text", v.name);
      let tindex = this.getModelNodeIndex(v.code);
      if (tindex > -1) {
        this.flowModel.node[tindex] = v;
      };
      /*
       *@description:如果修改的是文本，根据返回的文本信息，动态修改文本样式
       *@modifyContent:
       *@author: xuzhaoqian
       *@date: 2021-06-06 15:46:24
      */
      if (this.nodeType == "text") {
        this.textFontSize = v.fontType;
        this.myDiagram.model.setDataProperty(this.actGnode.data, "text", v.name);
        this.myDiagram.model.setDataProperty(this.actGnode.data, "color", v.fontColor);
        this.myDiagram.model.setDataProperty(this.actGnode.data, "fontSize", v.fontType + "pt helvetica, arial, sans-serif");
        this.myDiagram.model.setDataProperty(this.actGnode.data, "backgroundColor", v.backGroundColor);
      }
      this.hide();
    },
    hideFlow() {
      //关闭预览
      this.flowVisible = false;
    },
    saveFlowAttribute(v) {
      //保存流程属性，并关闭流程属性界面
      this.flowModel = v;
      this.flowVisible = false;
    },
    hideLink() {
      //关闭路由属性界面
      this.linkVisible = false;
      this.actGlink = null;
      this.actLink = null;
    },
    saveLink(v) {
      //保存路由信息
      this.myDiagram.model.setDataProperty(this.actGlink.data, "text", v.name);
      let tindex = this.getModelLinkIndex(v.code);
      if (tindex > -1) {
        this.flowModel.edge[tindex] = v;
      }
      this.hideLink();
    },
    close() {
      this.showFlowView = false;
    },
    getModelNode(tkey) {
      //通过节点key  获取 模型中的 对应节点的信息
      let rnode = null;
      this.flowModel.node.forEach((enode, index) => {
        if (enode.code == tkey) {
          rnode = enode;
        }
      });
      return rnode;
    },
    getModelNodeIndex(tkey) {
      //通过节点key  查找在模型节点中的位置
      let rindex = -1;
      this.flowModel.node.forEach((enode, index) => {
        if (enode.code == tkey) {
          rindex = index;
        }
      });
      return rindex;
    },
    getModelLink(tkey) {
      //通过节点key  获取 模型中的 对应路由的信息
      let rlink = null;
      this.flowModel.edge.forEach((elink, index) => {
        if (elink.code == tkey) {
          rlink = elink;
        }
      });
      return rlink;
    },
    getModelLinkIndex(tkey) {
      //通过节点key  查找在模型路由中的位置
      let rindex = -1;
      this.flowModel.edge.forEach((elink, index) => {
        if (elink.code == tkey) {
          rindex = index;
        }
      });
      return rindex;
    },
    closeWind() {
      this.isIconClick = false;
      this.showWind = false;
    },
    add() {
      //左侧菜单新增  流程类
      this.flowClass = null;
      this.showWind = true;
      this.addtitle = "新增流程类";
      this.activeitem = -1;
    },
    dropitemclick(item, dropItem, index) {
      //左侧流程菜单操作删除 编辑
      if (dropItem.name == "编辑") {
        this.addtitle = "编辑流程类";
        this.flowClass = item;
        let $state = item.state ? 1 : 0;
        this.$set(this.flowClass, "state", $state);
        this.showWind = true;
      }
      if (dropItem.name == "删除") {
        let param = {
          id: item.id,
        };
        workflowclassdelete(param).then((res) => {
          if (res.success) {
            this.activeitem = 0;
            this.workflowclassquery();
            this.message(res.msg, 1);
          } else {
            this.message(res.msg, 3);
          }
        });
      }
    },
    workflowclassquery() {
      // 查询流程类
      workflowclassquery(this.workflowparam).then((res) => {
        if (res.success) {
          // this.menuitems = res.info;
          this.menuitems = res.info.sort(function compareFunction(item1, item2) {
            return item1.name.localeCompare(item2.name);
          });
          this.activeitem = 0;
          if (this.menuitems[0] == undefined) {
            return;
          }
          this.flowClassId = this.menuitems[0].id;
          this.workflowdetail();
          this.workflowversion();
        } else {
          this.message(res.msg, 3);
        }
      });
    },
    async itemclick(e, index) {
      if (this.activeitem == index) return;
      if (this.isDiagramChange) {
        const confirm = await this.$message.confirm("是否保存该流程?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }).catch((err) => err);
        if (confirm !== "confirm") {
          this.$message.info("取消保存！");
        } else {
          //执行保存方法
          this.saveData();
        }
      }
      //流程类点击  查询流程信息
      this.activeitem = index;
      this.flowClassId = e.id;
      this.workflowdetail();
      this.workflowversion();
      //TODO 
      this.isDiagramChange = false;
    },
    async itemIconClick(e, index) {
      if (this.activeitem == index) {
        this.isIconClick = true;
        return;
      }
      if (this.isDiagramChange) {
        const confirm = await this.$message.confirm("是否保存该流程?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }).catch((err) => err);
        if (confirm !== "confirm") {
          this.$message.info("取消保存！");
        } else {
          //执行保存方法
          this.saveData();
        }
      }
      //流程类点击  查询流程信息
      this.activeitem = index;
      this.flowClassId = e.id;
      this.workflowdetail();
      this.workflowversion();
      //TODO 
      this.isDiagramChange = false;
    },
    workflowversion() {
      //查询流程版本
      workflowversion({
        classId: this.flowClassId,
      }).then((res) => {
        this.versions = res.info;
      });
    },
    workflowdetail() {
      //获取流程详情
      workflowdetail({
        classId: this.flowClassId,
      }).then((res) => {
        if (res.success) {
          if (res.info == null) {
            this.initFlow();
          } else {
            this.flowModel = res.info;
            this.version = this.flowModel.id;
            this.model = res.info.pic;
            this.myDiagram.model = go.Model.fromJson(this.model);
          }
          this.$set(this.myDiagram, "isReadOnly", false);
        } else {
          this.message(res.msg, 3);
        }
      });
    },
    workflowdetailByid() {
      workflowdetail({
        id: this.version,
      }).then((res) => {
        if (res.success) {
          if (res.info == null) {
            this.initFlow();
          } else {
            this.flowModel = res.info;
            this.model = res.info.pic;
            this.myDiagram.model = go.Model.fromJson(this.model);
          }
          this.$set(this.myDiagram, "isReadOnly", false);
        } else {
          this.message(res.msg, 3);
        }
      });
    },
    getIndex(id) {
      //获取左侧 流程 focus 的索引
      let ind = 0;
      this.menuitems.forEach((item, index) => {
        if (item.id == id) {
          ind = index;
        }
      });
      return ind;
    },
    async workflowclasssave(resinfo) {
      console.log("编辑保存。。。。。。。。。");
      //流程类  保存
      this.showWind = false;
      this.flowClass = resinfo;
      let $state = this.flowClass.state == 1 ? true : false;
      this.$set(this.flowClass, "state", $state);
      //this.$delete(this.flowClass,'state');
      workflowclasssave(this.flowClass).then((res) => {
        if (res.success) {
          workflowclassquery(this.workflowparam).then((resq) => {
            if (resq.success) {
              this.menuitems = resq.info.sort(function compareFunction(item1, item2) {
                return item1.name.localeCompare(item2.name);
              });
              if (this.isIconClick) {
                this.isIconClick = false;
                return
              };
              // this.menuitems = resq.info;
              this.activeitem = this.getIndex(res.info.value);
              this.flowClassId = res.info.value;
              this.workflowdetail();
              this.workflowversion();
            } else {
              this.message(res.msg, 3);
            }
          });
        } else {
          this.message(res.msg, 3);
        }
      });
    },
    search(data) {
      //流程类查询
      this.workflowparam.content = data;
      this.workflowclassquery();
    },
    initFlow() {
      //新增流程初始化
      this.myDiagram.model = go.Model.fromJson({
        class: "go.GraphLinksModel",
        linkFromPortIdProperty: "fromPort",
        linkToPortIdProperty: "toPort",
        nodeDataArray: [],
        linkDataArray: [],
      });
      this.flowModel = {
        classId: this.flowClassId,
        code: null,
        version: 1.0,
        active: true,
        jpush: true,
        sms: false,
        node: [],
        edge: [],
        vvar: [],
      };
      this.flowModel.code = "F-" + this.randomString(14);
    },
    openFlowAttribute() {
      this.flowVisible = true;
    },
    saveData() {
      //保存流程信息，把gojs的model 存到模型的pic中
      this.$set(this.flowModel, "pic", this.myDiagram.model.toJSON());
      let this_ = this;
      if (this.flowModel.node.length == 0) {
        this.message("流程没有节点和路由，保存失败", 3);
        return;
      }
      console.log("222222222    " + this.flowModel.pic)

      workflowsave(this.flowModel).then((res) => {
        if (res.success) {
          if (!this_.flowModel.id) {
            //如果是空id 就赋值   this.flowModel  code  value
            res.info.forEach((item, index) => {
              if (item.code.indexOf("F-") > -1) {
                this_.flowModel.id = item.value;
                this_.version = item.value;
              }
              if (item.code.indexOf("N-") > -1) {
                let tindex = this_.getModelNodeIndex(item.code);
                this_.flowModel.node[tindex].id = item.value;
              }
              if (item.code.indexOf("L-") > -1) {
                let tindex = this_.getModelLinkIndex(item.code);
                this_.flowModel.edge[tindex].id = item.value;
              }
            });
          }
          this.workflowdetail();
          this.workflowversion();
          this.message(res.msg, 1);
        } else {
          this.message(res.msg, 3);
        }
      });
      //				var model = this.myDiagram.model.toJSON(); //获得整个画布的json
      //				model = eval('(' + model + ')'); //若格式异常抓一下
      //				var nodes = model.nodeDataArray; //取出所有节点
      //				var Links = model.linkDataArray; //取出所有线
    },
    delflow() {
      if (this.flowModel.id) {
        this.$messageBox("确定要删除当前流程！").then((res) => {
          if (res.action) {
            workflowdelete({
              id: this.flowModel.id,
            }).then((resD) => {
              if (resD.success) {
                this.workflowversion();
                this.workflowdetail();
                this.message(resD.msg, 1);
              } else {
                this.message(resD.msg, 3);
              }
            });
          }
        });
      } else {
        this.message("删除成功！", 1);
        this.workflowdetail();
      }
    },

    clone() {
      let hased = false;
      this.versions.forEach((v, index) => {
        if (v.version == this.flowModel.version) {
          hased = true;
        }
      });
      if (!hased) {
        this.flowModel.id = null;
        this.flowModel.node.forEach((node, index) => {
          node.id = null;
        });
        this.flowModel.edge.forEach((edge, index) => {
          edge.id = null;
        });
        this.saveData();
      } else {
        this.message(
          "流程版本" +
          this.flowModel.version +
          "已经存在！双击流程编辑空白处，修改版本！",
          3
        );
      }
    },
    //测试 发送 要删除
    startflow() {
      this.wfClassId = 45;
      this.sendtype = 0;
      this.showFlowSend = true;
    },
    sendflow() {
      this.instNodeId = 7;
      this.sendtype = 1;
      this.showFlowSend = true;
    },
    FlowSendsave() {
      this.showFlowSend = false;
    },
    closeFlowSend() {
      this.showFlowSend = false;
    },
    writeJson() {
      this.activemodel = this.myDiagram.model.toJSON();
      this.showFlowView = true;
      this.instNodeId = 160;
      this.wfInstId = 127;
    },
  },
};
</script>

<style scoped>
#myPaletteDiv {
  width: 110px;
  background: var(--system-page-content-bgc);
  border: 1px solid var(--button-border-color);
  margin: 10px 0px 10px 10px;
  border-radius: 6px;
}

#myPaletteDiv>>>canvas {
  margin-top: 10px !important;
  height: 280px;
}

#myDiagramDiv {
  flex-grow: 1;
  background: var(--system-page-content-bgc);
  border-radius: 6px;
}

#myDiagramDiv>>> :focus,
#myPaletteDiv>>> :focus {
  outline: none !important;
}

.center {
  width: 100%;
  height: calc(100% - 55px);
}

.iconxitongpingtai-liuchengguanli {
  font-size: 24px;
  margin: 0px 14px 0px 20px;
  color: var(--button-active-back-color);
}

.content {
  /*height: calc(100% - 68px);
		border-radius: 6px;
		padding: 12px;*/
  display: flex;
  flex-direction: row;
}

.page-flow-detail {
  margin-left: 12px;
  width: 100%;
  background: var(--system-page-content-bgc);
  border: 1px solid var(--system-page-content-border-color);
  border-radius: 6px;
  position: relative;
  height: 100%;
}

.tool {
  display: flex;
  justify-content: space-between;
  height: 32px;
  padding-left: 12px;
  background: rgba(204, 204, 204, 0);
  border-bottom: var(--cell-tool-line);
  border-radius: 4px 4px 0px 0px;
}

.version {}

.version>>>.el-input__inner {
  height: 24px !important;
  line-height: 24px !important;
  width: 100%;
  margin-top: 4px;
}

.version>>>.el-input__icon {
  height: 32px !important;
  line-height: 32px !important;
}

.version span {
  height: 32px;
  line-height: 32px;
  width: 80px;
  margin-right: 13px;
  color: var(--system-form-text-color);
}

.flow-btn {
  height: 31px;
  line-height: 31px;
  width: 30px;
  font-size: 18px;
}

.btn {
  background: rgba(210, 211, 214, 1);
  width: 18px;
  height: 18px;
  margin-right: 12px;
  margin-top: 7px;
}

.btn:active {
  background: #8a2be2;
}
</style>
